/*
 * @Author       : ShiJunJie
 * @Date         : 2022-04-26 16:12:33
 * @LastEditors  : ShiJunJie
 * @LastEditTime : 2022-04-27 11:26:42
 * @FilePath     : /src/utils/https.ts
 * @Descripttion : 请求拦截器
 */
import axios from 'axios'
import storage from 'good-storage'

import { message } from 'ant-design-vue'
import { User } from '@/api/user'
import { useRequest, setGlobalOptions } from 'vue-request'
import validationCode from './validationCode'


console.log('meta', import.meta)
const axiosConfig = {
  // API 请求的默认前缀
  baseURL: import.meta.env.VITE_NODE_ENV === 'pro' ? `${import.meta.env.VITE_APP_API_URL}` : undefined,
  timeout: 20000, // 请求超时时间
  // withCredentials: true
}
// 创建 axios 实例
const request = axios.create(axiosConfig)

// 异常拦截处理器
const errorHandler = (error: any) => {
  // console.log(error)
  if (error.response) {
    const data = error.response.data
    // 从 localstorage 获取 token
    const user = storage.get('USER_TOKEN')
    if (error.response.status === 403) {
      console.error({
        message: 'Forbidden',
        description: data.message,
      })
    }
    if (error.response.status === 401 && !(data['result'] && data['result']['isLogin'])) {
      console.error({
        message: 'Unauthorized',
        description: 'Authorization verification failed',
      })
      if (user) {
        storage.clear()
        setTimeout(() => {
          window.location.reload()
        }, 1500)
      }
    }
  }

  const errMsgMap = {
    'Network Error': '无法连接网络，请确认网络连接是否正常',
    'Request failed with status code 500': '服务器响应异常 - 请联系管理员',
    'Request failed with status code 400': '参数格式不正确 - 请联系管理员',
    'timeout of 20000ms exceeded': '请求超时 请重试',
  }

  const errMsg =
    errMsgMap[error?.response?.data?.message || error?.message] || error?.response?.data?.message || error?.message
  const ret = { code: 999999, msg: errMsg, data: error?.response?.data }
  if (errMsg !== '中断请求') {
    message.destroy()
    message.error(errMsg)
    console.error('错误拦截器', '\n', ret, '\n', error)
  }
  return ret
}

// 定义全局参数
// window['axiosCancel'] = []
// request interceptor  请求拦截器
request.interceptors.request.use(async (config) => {
  if (config.method === 'get') {
    // config.cancelToken = new axios.CancelToken((cancel) => {
    //   window['axiosCancel'].push({
    //     cancel,
    //   })
    // })
    let data = config.data
    if (data) {
      config.params = config?.data
    }
  }

  const method = ['post', 'put', 'patch', 'delete']
  if (method.indexOf(config.method) !== -1) {
    console.warn(`调用了 ${config.method} 请求`)
    // headers:{'Content-Type':'multipart/form-data'}
    config.headers['Content-Type'] = 'application/json'
    config.data = config?.data?.data || config?.data
  }


  console.log('请求拦截器\n', config)
  return new Promise((resolve, reject) => {
    // 让每个请求携带自定义 token 请根据实际情况自行修改
    if (storage.get('USER_TOKEN')) {
      let user = storage.get('USER_TOKEN')
      let token = user && (user.authorization || user.token || 'test')
      config.headers['Authorization'] = token
      /** token 失效重新拉取
      if (user.exp - new Date().getTime() <= 300000) {
        axios.create({
          ...axiosConfig,
          headers: { 'Authorization': token }
        }).put(`/manage/v1/access`).then(success => {
          const { data: res } = success
          console.log(res);
          if (!res.code) {
            storage.set('USER_TOKEN', res.data)
            config.headers['Authorization'] = res.data.token
          } else {
            localStorage.clear()
            location.reload()
          }
        }).catch(err => {
          console.log(err);
          localStorage.clear()
          location.reload()
        });
      }
      */
    }
    resolve(config)
  })
}, errorHandler)

// response interceptor  响应拦截器
request.interceptors.response.use((response) => {
  const _response = { ...response.data }
  if (_response.code !== 0) {
    const resData = _response.data
    let msg = ''
    if (resData) {
      Object.keys(resData).forEach((e) => {
        msg += `${resData[e]}`
      })
    }
    _response.msg = validationCode(_response.code) || msg || _response.msg
    _response.msg && message.warn(_response.msg)
  }
  console.log(`响应拦截器`, _response)
  return Promise.resolve(_response)
}, errorHandler)

// export default request
/**
 * useRequest 全局配置
 * https://www.attojs.com/api/global-options.html#公共选项
 */
setGlobalOptions({
  manual: false, // 当 manual 设置为 true 时，你需要手动触发 run 才会发起请求
  loadingDelay: 200, // 通过设置延迟的毫秒数，可以延迟 loading 变成 true 的时间，有效防止闪烁。
  refreshOnWindowFocus: true, // 当设置为 true 时，则在浏览器窗口触发 focus 和 visibilitychange 时，会重新发起请求。
  refocusTimespan: 5000, // 当 refreshOnWindowFocus 设置为 true 时，你可以通过设置间隔的毫秒数，来限制 refresh 的执行间隔，默认为 5000ms
  debounceInterval: 300, // 通过设置需要延迟的毫秒数，进入防抖模式。此时如果频繁触发 run ，则会以防抖策略进行请求。
  throttleInterval: 300, // 通过设置需要节流的毫秒数，进入节流模式。此时如果频繁触发 run ，则会以节流策略进行请求。
  cacheTime: 600000, // 当开启缓存后，你可以通过设置 cacheTime 来告诉我们缓存的过期时间。当缓存过期后，我们会将其删除。默认为 600000 毫秒，即 10 分钟
  // staleTime: 60000, // 如果你能确保缓存下来的数据，在一定时间内不会有任何更新的，我们建议你设置一个合理的毫秒数
  errorRetryCount: 5, // it will retry 5 times
  errorRetryInterval: 5000, // The retry interval is 5 seconds
})
const refRequest = {
  refGet: (url: string, data?: any, options?: any) => useRequest(() => request.get(url, data ? { data } : undefined), options),
  refPost: (url: string, data?: any, options?: any) => useRequest(() => request.post(url, data ? { data } : undefined), options),
  refPut: (url: string, data?: any, options?: any) => useRequest(() => request.put(url, data ? { data } : undefined), options),
  refPatch: (url: string, data?: any, options?: any) => useRequest(() => request.patch(url, data ? { data } : undefined), options),
  refDelete: (url: string, data?: any, options?: any) => useRequest(() => request.delete(url, data ? { data } : undefined), options),
  retTest: (url: string, data?: any, options?: any) => useRequest(() => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        return Math.random() > 0.5 ? resolve({ code: 0, data: Math.random(), msg: 'success' }) : reject({ code: 500, data: Math.random(), msg: 'error' })
      }, 1000);
    })
  }, options),
}
const newRequest = { ...request, ...refRequest }
export default newRequest
